import 'dart:convert';
import 'dart:io';
import 'package:string_scanner/string_scanner.dart';

void main(List<String> args) async {
  File file = File(
      "/Users/yaplekde/Development/flutter_projects/mobile-app/lib/l10n/all_string.json");
  print(file.path);

  Directory directory = Directory(
      '/Users/yaplekde/Development/flutter_projects/mobile-app/lib/src');
  print(directory.path);
  List<String> allString = [];
  await readDirectory(directory, allString);
  allString = allString.toSet().toList();
  allString.removeWhere((element) =>
      element.startsWith('package:') ||
      element.isEmpty ||
      RegExp(r'\w+Page$').hasMatch(element) ||
      element.endsWith('.dart') ||
      element.contains('_') ||
      !element.startsWith(RegExp('[A-Z]')) ||
      element.length == 1);
  File intlEn = File(
      "/Users/yaplekde/Development/flutter_projects/mobile-app/lib/l10n/intl_en.arb");
  final data = await intlEn.readAsString();
  Map<String, dynamic> jsonMap = json.decode(data);
  for (final item in jsonMap.entries) {
    if (allString.contains(item.value)) {
      allString.remove(item.value);
    }
  }
  Map<String, String> result = {};
  for (final item in allString) {
    String key = formatKey(item);
    final _key = key
        .replaceAll('\'', '_')
        .replaceAll(' ', '')
        .replaceAll('\n', '_')
        .replaceAll(RegExp(r'\${(.*)}'), '')
        .replaceAll(' ', '')
        .replaceAll('&', '')
        .replaceAll('’', '')
        .replaceAll('_/', '')
        .replaceAll('?', '')
        .replaceAll(':', '')
        .replaceAll('.', '')
        .replaceAll('(', '')
        .replaceAll(')', '')
        .replaceAll('-', '')
        .replaceAll('@', '')
        .replaceAll(',', '')
        .replaceAll('/', '_');
    result[_key] = item.replaceAll(RegExp(r'\${(.*)}'), '');
  }
  file.writeAsString(JsonEncoder.withIndent('  ').convert(result));
}

Future<void> readDirectory(Directory directory, List<String> allString) async {
  print('==>read directory path:${directory.path}');
  final libList = directory.listSync();
  for (final file in libList) {
    if (await FileSystemEntity.isDirectory(file.path)) {
      await readDirectory(Directory(file.path), allString);
    } else {
      print('======>read file path:${directory.path}');
      final mFile = File(file.path);
      final sourceContent = await mFile.readAsString();
      void collectionString(
        int start,
        int end,
      ) {
        final resultContent = sourceContent.substring(start, end);
        allString.add(resultContent);
      }

      final entities = getStringFromFile(sourceContent);
      for (final entity in entities) {
        collectionString(
            entity.start + entity.ignoreNumber + (entity.isPrefixR ? 1 : 0),
            entity.end - entity.ignoreNumber);
      }
    }
  }
}

bool isUpperCase(int c) => c >= 65 && c <= 90;

String formatKey(String name) {
  final codeList = name.codeUnits;
  var result = <int>[];
  for (var i = 0; i < codeList.length; i++) {
    final code = codeList[i];
    if (String.fromCharCode(code) == ' ') {
      result.addAll('_'.codeUnits);
    } else {
      result.addAll(String.fromCharCode(code).toLowerCase().codeUnits);
    }
  }
  return String.fromCharCodes(result)
      .replaceAll('\\n', '_')
      .replaceAllMapped(RegExp("\n(\w+)\n"), (match) {
    for (var i = 0; i < match.groupCount; i++) {
      print('${match[i]}');
    }
    return '_${match[1]}';
  });
}

List<StringCommendEntity> getStringFromFile(String fileContent) {
  var entities = <StringCommendEntity>[];
  final scanner = StringScanner(fileContent);
  var lastPosition = scanner.position;
  var contentLength = fileContent.length;
  while (!scanner.isDone) {
    scanner.scan(RegExp(r'\s+'));
    if (scanner.scan(RegExp(r'"""(?:[^"\\]|\\(.|\n))*"""')) ||
        scanner.scan(RegExp(r"'''(?:[^'\\]|\\(.|\n))*'''"))) {
      final ignoreIndex = 3;
      entities.add(StringCommendEntity(
        scanner.lastMatch.start,
        scanner.lastMatch.end,
        ignoreIndex,
      ));
      continue;
    }

    if (scanner.scan(RegExp(r'r"""(?:[^"\\]|\\(.|\n))*"""')) ||
        scanner.scan(RegExp(r"r'''(?:[^'\\]|\\(.|\n))*'''"))) {
      final ignoreIndex = 3;
      entities.add(StringCommendEntity(
        scanner.lastMatch.start,
        scanner.lastMatch.end,
        ignoreIndex,
        true,
      ));
      continue;
    }

    if (scanner.scan(RegExp(r'".*?"')) || scanner.scan(RegExp(r"\'.*?\'"))) {
      final ignoreIndex = 1;
      entities.add(StringCommendEntity(
        scanner.lastMatch.start,
        scanner.lastMatch.end,
        ignoreIndex,
      ));

      continue;
    }

    if (scanner.scan(RegExp(r'r".*?"')) || scanner.scan(RegExp(r"r\'.*?\'"))) {
      final ignoreIndex = 1;
      entities.add(StringCommendEntity(
          scanner.lastMatch.start, scanner.lastMatch.end, ignoreIndex, true));
      continue;
    }
    if (scanner.position == contentLength) {
      break;
    }
    if (lastPosition == scanner.position) {
      scanner.position = lastPosition + 1;
    }
    lastPosition = scanner.position;
  }
  return entities;
}

class StringCommendEntity {
  final int start;
  final int end;

  //要忽略的number
  final int ignoreNumber;

  //是否有r开头
  final bool isPrefixR;

  StringCommendEntity(this.start, this.end, this.ignoreNumber,
      [this.isPrefixR = false]);
}
